/*
 * JHeuristics - The Java Meta-Heuritics Library
 * Copyright (C) 2004-2005, Universidade Federal de Campina Grande. All rights reserved.
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
package org.jheuristics.ga.operators.selectors;

import java.io.Serializable;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import org.epanetgrid.otimizacao.ag.InviaveisSelector;
import org.jheuristics.Individual;
import org.jheuristics.ga.DefaultPopulation;
import org.jheuristics.ga.GAConfig;
import org.jheuristics.ga.GAStatus;
import org.jheuristics.ga.Population;
import org.jheuristics.ga.operators.Selector;


/**
 * TODO
 *
 *	Seleciona os melhores individuos invi�veis para cara fun��o
 * @author Vin�cius Ferraz
 */
public class BestIndividualsInviaveisSelector implements Selector, Serializable {

    /**
     * TODO
     *
     * @param population
     * @param howMany
     * @param status
     * @param config
     * @return
     * @see org.jheuristics.ga.operators.Selector#select(org.jheuristics.ga.Population, int, org.jheuristics.ga.GAStatus, org.jheuristics.ga.GAConfig)
     */
    public Individual[] select(Population population, int howMany, GAStatus status, GAConfig config) {
        if (null == population) {
			// TODO: ERROR MSG
			throw new NullPointerException();
		}
		if (0 > howMany || population.size() < howMany) {
			// TODO: ERROR MSG
			throw new IllegalArgumentException();
		}
		
		
		List<Individual> minimos = new LinkedList<Individual>();
		
		DefaultPopulation inviaveis = new DefaultPopulation();
		inviaveis.addIndividuals(new InviaveisSelector().select(population, howMany, status, config));
		
		Individual[] individuos = inviaveis.toIndividualArray();
		if(individuos.length == 0) {
			return new Individual[0];
		}
		
		for (int i = 0 ; i < ((List) individuos[0].getDataApplication()).size(); i++) {
			int index = 0;
			Comparable min = (Comparable)((List) individuos[0].getDataApplication()).get(i);
			
			for (int j = 1; j < individuos.length; j++) {
				Comparable value = (Comparable)((List) individuos[j].getDataApplication()).get(i);
			
				if (min.compareTo(value) > 0) {
					index = j;
					min = value;
				}
			}
			if(!minimos.contains(minimos.add(individuos[index]))) {
				minimos.add(individuos[index]);
			}
		}
		
		
		

//		if(howMany > 0) {
//			Individual[] pop = choose(sortPopulation(population), howMany).toIndividualArray();
			
			return minimos.toArray(new Individual[0]);
//		}else {
//			buffer.append(new Individual[0]);
//			logger.log(SPLogger.OTIMIZACAO, SPLogger.DEBUG, buffer);
//			return new Individual[0];
//		}
		
//        return (howMany > 0) ? choose(sortPopulation(population), howMany).toIndividualArray() : new Individual[0];
    }
    
    /**
     * TODO
     *
     * @param population
     * @return
     */
    protected Population sortPopulation(Population population) {
    	Population sorted = new DefaultPopulation();
    	sorted.addIndividuals(population);
    	sorted.sort();
    	return sorted;
    }
    
    /**
     * TODO
     *
     * @param population
     * @param howMany
     * @return
     */
    protected Population choose(Population population, int howMany) {
		DefaultPopulation result = new DefaultPopulation();
		if (howMany > 0) {
			Iterator it = population.iterator();
			for(int i = 0; i < howMany; i++) {
			    result.addIndividual((Individual) it.next());
			}
		}
		result.sort();
		return result;
    }
    
}
